package test;

import java.util.concurrent.TimeUnit;

/**
 * @author Jason Wilson
 * @description
 * 实际应用场景
 * 1.网络请求重试：在调用网络API时，可以使用指数退避策略来处理短暂的网络故障。
 * 2.分布式系统协调：在分布式系统中协调资源或操作时，防止多个节点同时对共享资源进行高频请求。
 * 3.处理外部服务依赖：如数据库或第三方服务在短时间内不可用时，通过指数退避策略进行重试，提高成功率并避免过度负载。
 * 指数退避策略通过增加重试之间的间隔时间，结合随机化，能有效减少系统负载，避免重试风暴和提高整体操作成功率。
 * @date 2024-05-2024/5/15-14:35
 */
public class ExponentialBackoff {

    private final long initialDelay;
    private final long maxDelay;
    private final double multiplier;
    private long currentDelay;

    public ExponentialBackoff(long initialDelay, long maxDelay, double multiplier) {
        this.initialDelay = initialDelay;
        this.maxDelay = maxDelay;
        this.multiplier = multiplier;
        this.currentDelay = initialDelay;
    }

    public long nextDelay() {
        long delay = currentDelay;
        currentDelay = Math.min((long) (currentDelay * multiplier), maxDelay);
        return delay;
    }

    public void reset() {
        currentDelay = initialDelay;
    }

    public static void main(String[] args) {
        ExponentialBackoff backoff = new ExponentialBackoff(500, 16000, 2.0);

        for (int i = 0; i < 10; i++) {
            long delay = backoff.nextDelay();
            System.out.println("Retry " + (i + 1) + ": waiting for " + delay + " milliseconds");
            try {
                TimeUnit.MILLISECONDS.sleep(delay);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException(e);
            }
        }

        backoff.reset();
    }

}
